<?php
/**
 * 权限操作接口
 *
 * @author Mo yi <root@imoi.cn>
 * @link   http://www.imoi.cn
 * @copyright Copyright &copy; 2010-2012 DuoLam Software LLC
 * @license http://www.imoi.cn/license/
 * @version $Id: dpAuth.php 1 2012-04-22 14:41:54Z Mo.yi $
 * @package db
 * @since 1.0
 */

class dpAuth extends dpComponent
{
	/**
	 * 数据库连接句柄
	 */
	protected $db;

	/**
	 * 角色句柄
	 */
	protected $role;

	/**
	 * 行为句柄
	 */
	protected $behavior;

	/**
	 * 当前新增的组ID
	 */
	private $_groupId;

	/**
	 * 构造方法，连接数据库
	 * @param string $link 从库名，默认连接主库
	 */
	public function __construct($link = '')
	{
		$this->db = D::app()->db()->createSql();
		$this->role = new dpAuthRole($this);
		$this->behavior = $this->getBehavior();
	}

	/**
	 * 获取数据库连接
	 * @return object 数据库连接句柄
	 */
	public function getDb()
	{
		return $this->db;
	}

	/**
	 * 获取角色实例
	 */
	public function getRole()
	{
		return $this->role;
	}

	/**
	 * 获取行为实例
	 */
	public function getBehavior()
	{
		return $this->role->getBehavior();
	}

	/**
	 * 建立用户角色
	 * @param int    $uid      用户ID
	 * @param string $roleName 角色名
	 * @param int    $fatherId 角色父ID，默认无父角色
	 * @param boolean $enabled 是否启用角色，默认启用
	 * @param string $description 角色描述，默认为空
	 * @return object 返回行为实例
	 */
	public function createUserRole($uid, $roleName, $fatherId = 0, $enabled = true, $description = null)
	{
		if (empty($uid) || empty($roleName)) return false;

		$behavior = $this->role->createRole($roleName, $fatherId, $enabled, $description);
		$roleId   = $this->role->getRoleId();
		$data = array
		(
			'uid' => $uid,
			'rid' => $roleId,
		);
		$this->db->insert('{user_role}', $data);
		return $behavior;
	}

	/**
	 * 建立组
	 * @param string  $groupName   组名
	 * @param boolean $enabled     是否启用组，默认启用
	 * @param boolean $extends     是否启用角色继承，默认不启用
	 * @param string  $description 组描述，默认为空
	 * @return object 角色实例
	 */
	public function createGroup($groupName, $enabled = true, $extends = false, $description = null)
	{
		if (empty($groupName)) return false;

		$groupData = $this->db->select('gid')
					 ->from('{group}')
					 ->where('group_name=:group',array(':group'=>$groupName))
					 ->find();

		if ($groupData) return false;

		$data = array
		(
			'group_name'		=> $groupName,
			'is_group_enabled'  => $enabled ? 1 : 0,
			'is_extends'		=> $extends ? 1 : 0,
			'description'		=> $description,
		);
		$this->_groupId = $this->db->insert('{group}', $data);
		return $this;
	}

	/**
	 * 建立组角色
	 * @param string $roleName 角色名
	 * @param string $groupId  组ID
	 * @param int    $fatherId 角色父ID，默认无父角色
	 * @param boolean $enabled 是否启动角色，默认启用
	 * @param string $description 角色描述，默认为空
	 * @return object 返回行为实例
	 */
	public function createGroupRole($roleName, $groupId=0, $fatherId = 0, $enabled = true, $description = null)
	{
		if (empty($roleName)) return false;

		$behavior = $this->role->createRole($roleName, $fatherId, $enabled, $description);
		$roleId   = $this->role->getRoleId();
		$data = array
		(
			'gid' => empty($this->_groupId) ? (int)$groupId : $this->_groupId,
			'rid' => $roleId,
		);

		if ($data['gid'] <= 0) return false;

		$this->db->insert('{group_role}', $data);
		return $behavior;
	}

	/**
	 * 移除用户一个角色
	 * 移除角色，则会把该角色下的行为全部删除
	 * @param int $uid 用户ID
	 * @param string $roleName 角色名
	 * @return boolean 成功返回true
	 */
	public function removeUserRole($uid, $roleName)
	{
		if (empty($uid) || empty($roleName)) return false;

		$rid = $this->role->removeRole($roleName);

		if ($rid) {
			$this->db->delete('{user_role}',array('and', 'uid=>'.(int)$uid, 'rid=>'.$rid));
			$this->behavior->removeBehaviorByRid($rid);
			return true;
		}
		else
			return false;
	}

	/**
	 * 移除用户所有角色
	 * 移除角色，则会把该角色下的行为全部删除
	 * @param int $uid 用户ID
	 * @return boolean 成功返回true
	 */
	public function removeUserRoles($uid)
	{
		if (empty($uid)) return false;

		$rid = $this->role->removeRoles('{user_role}', 'uid' , $uid);

		if ($rid) {
			$this->db->delete('{user_role}',array('and', 'uid=>'.(int)$uid, array('in', 'rid', $rid)));
			$this->behavior->removeBehaviorAll('rid', $rid);
			return true;
		}
		else
			return false;
	}


	/**
	 * 移除组角色
	 * 移除角色，则会把该角色下的行为全部删除
	 * @param int $gid 组ID
	 * @param string $roleName 角色名
	 * @return boolean 成功返回true
	 */
	public function removeGroupRole($gid, $roleName)
	{
		if (empty($gid) || empty($roleName)) return false;

		$rid = $this->role->removeRole($roleName);

		if ($rid) {
			$this->db->delete('{group_role}',array('and', 'gid=>'.(int)$uid, 'rid=>'.$rid));
			$this->behavior->removeBehaviorByRid($rid);
			return true;
		}
		else
			return false;
	}

	/**
	 * 移除组所有角色
	 * 移除角色，则会把该角色下的行为全部删除
	 * @param int $uid 用户ID
	 * @return boolean 成功返回true
	 */
	public function removeGroupRoles($uid)
	{
		if (empty($uid)) return false;

		$rid = $this->role->removeRoles('{group_role}', 'gid' , $uid);

		if ($rid) {
			$this->db->delete('{group_role}',array('and', 'gid=>'.(int)$uid, array('in', 'rid', $rid)));
			$this->behavior->removeBehaviorAll('rid', $rid);
			return true;
		}
		else
			return false;
	}

	/**
	 * 移除行为
	 * @param int $behaviorId 行为ID
	 * @return boolean
	 */
	public function removeBehavior($behaviorId)
	{
		if (empty($behaviorId)) return false;

		$this->behavior->removeBehaviorById($behaviorId);
		return false;
	}

	/**
	 * 移除行为中的某个action(动作)
	 * @param int $behaviorId 行为ID
	 * @param string $action 动作名
	 * @return boolean
	 */
	public function removeBehaviorAction($behaviorId, $action)
	{
		if (empty($behaviorId) || empty($action)) return false;

		$behavior = $this->behavior->getBehavior($behaviorId, 'access_action');
		$actions = explode('|', $behavior['access_action']);

		if (($key = array_search($action, $actions)) !== false)
			unset($actions[$key]);
		else
			return false;

		$actions = implode('|', $actions);
		$this->behavior->updateBehavior($behaviorId, array('access_action'=>$actions));
		return true;
	}

	/**
	 * 给行为添加动作
	 * @param int $behaviorId
	 * @param array $actions 动作列表
	 * @return boolean
	 */
	public function addBehavior($behaviorId, array $actions)
	{
		if (empty($behaviorId) || empty($actions)) return false;

		$behavior = $this->behavior->getBehavior($behaviorId, 'access_action');
		$_actions = explode('|', $behavior['access_action']);
		$actions  = implode('|', array_unique(array_merge($_actions, $actions)));
		$this->behavior->updateBehavior($behaviorId, array('access_action'=>$actions));
		return true;
	}

	/**
	 * 修改行为
	 * @param int $behaviorId 行为ID
	 * @param array $behavior 行为列表，module, control, action
	 * @return boolean
	 */
	public function modifyBehavior($behaviorId, array $behavior)
	{
		if (empty($behavior) || empty($behavior)) return false;

		if (isset($behavior['module']))
			$data['access_module']  = $behavior['module'];

		if (isset($behavior['control']))
			$data['access_control'] = $behavior['control'];

		if (isset($behavior['action']))
			$data['access_action']  = implode('|', $behavior['action']);

		$this->behavior->updateBehavior($behaviorId, $data);
		return true;
	}

	/**
	 * 获取基于用户的所有角色
	 * @param int $uid  用户id
	 * @return array 用户角色
	 */
	public function getUserRole($uid, $true = false)
	{
		if (empty($uid)) return false;

		$extend = $this->db->find('SELECT is_extends FROM {user} WHERE uid='.$uid);

		if (empty($extend)) return false;

		$field = $true ? 'rid' : '*';

		if ($extend['is_extends']) {
			$roles = $this->db->finds('SELECT '. $true ? 'rid' : '*' .' FROM {role}');
			$curUserRole = $this->db->select()->from('{role}')
			->where('rid IN (SELECT rid FROM {user_role} WHERE uid='.$uid.')')
			->finds();

			if ($curUserRole !== array()) {
				$data = array();
				foreach($curUserRole as $key => $val)
					if($d = $this->_getChildRole($val['rid'], $roles)) $data = array_merge($data, $d);
			}

			foreach ($data as $v) $this->unique($curUserRole, $v['rid']);
			return array_merge($curUserRole, $data);
		} else {
			return $this->db->select($field)
					->from('{role}')
					->where('rid IN (SELECT rid FROM {user_role} WHERE uid='.$uid.')')
					->finds();
		}
	}

	/**
	 * 获取基于组的所有角色
	 * @param int $gid  组id
	 * @return array 组角色
	 */
	public function getGroupRole($gid, $true = false)
	{
		if (empty($gid)) return false;

		$extend = $this->db->find('SELECT is_extends FROM {group} WHERE gid='.$gid);

		if (empty($extend)) return false;

		$field = $true ? 'rid' : '*';

		if ($extend['is_extends']) {
			$roles = $this->db->finds('SELECT '. $field .' FROM {role}');
			$curUserRole = $this->db->select()->from('{role}')
			->where('rid IN (SELECT rid FROM {group_role} WHERE gid='.$gid.')')
			->finds();

			if ($curUserRole !== array()) {
				$data = array();
				foreach($curUserRole as $key => $val)
					if($d = $this->_getChildRole($val['rid'], $roles)) $data = array_merge($data, $d);
			}

			foreach ($data as $v) $this->unique($curUserRole, $v['rid']);
			return array_merge($curUserRole, $data);
		} else {
			return $this->db->select($field)
					->from('{role}')
					->where('rid IN (SELECT rid FROM {group_role} WHERE gid='.$gid.')')
					->finds();
		}
	}

	/**
	 * 获取一个用户的所有行为
	 * @param int $uid
	 * @return array
	 */
	public function getUserBehavior($uid, $true = false)
	{
		$rows = $this->getUserRole($uid, true);
		$ids  = array();

		if (empty($rows)) return false;

		foreach ($rows as $row) $ids[] = $row['rid'];

		return $this->db->select($true ? 'bid' : '*')
				->from('{behavior}')
				->where(array('in', 'rid', $ids))
				->finds();
	}

	/**
	 * 获取一个组的所有行为
	 * @param int $uid
	 * @return array
	 */
	public function getGroupBehavior($uid, $true = false)
	{
		$rows = $this->getGroupRole($uid, true);

		if (empty($rows)) return false;

		foreach ($rows as $row) $ids[] = $row['rid'];

		return $this->db->select($true ? 'bid' : '*')
				->from('{behavior}')
				->where(array('in', 'rid', $ids))
				->finds();
	}

	/**
	 * 获取子角色权限(经过思量，只继承一级子角色)
	 * @param int $rid 子角色ID
	 * @param array $roles 角色
	 */
	private function _getChildRole($rid, &$roles)
	{
		if (empty($roles)) return false;

		foreach ($roles as $k => $v) {
			if ($v['father_role_id'] != 0 && $v['father_role_id']==$rid) $data[] = $v;
		}

		return empty($data) ? false : $data;
	}

	/**
	 * 去除重复的角色
	 */
	protected function unique(&$data, $rid)
	{
		foreach ($data as $k => $v) if($v['rid'] == $rid) unset($data[$k]);
	}

	/**
	 * 获取一个用户的信息
	 * @param int $uid 用户ID
	 * @param string $select 字段列表，默认所有
	 */
	public function getUserInfo($uid, $select = '*')
	{
		return $this->db->select($select)->from('{user}')->
				where('uid='.(int)$uid)->find();
	}

}
?>